home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1998
/
MacHack 1998.toast
/
The Hacks!
/
Interim Executive Decision
/
SelectorFunction.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-21
|
3KB
|
214 lines
#include <A4Stuff.h>
#include <Errors.h>
#include <Gestalt.h>
#include <TextUtils.h>
// Constants
#define kAllocChunk 20
// Public Routines
pascal void* main(int iRoutineSelector);
pascal
OSErr
MySelectorFunction
(
OSType selector,
long* response
);
pascal OSErr FindSelector(OSType selector, long* value);
pascal OSErr RegisterSelector(OSType selector, long value);
// The main entry point
pascal
void* // The routine pointer
main
(
int iRoutineSelector // The routine name
)
{
long oldA4 = SetCurrentA4 ();
void* retval;
if (iRoutineSelector == 1)
{
retval = (void*)RegisterSelector;
}
else
{
retval = (void*)FindSelector;
}
SetA4 (oldA4);
return (retval);
}
// Globals
static Handle gSelectors = nil;
static Handle gValues = nil;
static long gAllocSize = 0;
static long gPatchCount = 0;
// Local routines.
static long FindPatch(OSType selector);
static OSErr SetGestaltRoutine(OSType selector);
// Find a patched selector.
long FindPatch(OSType selector)
{
long oldA4 = SetCurrentA4 ();
long i;
for (i = 0; (i < gPatchCount) && gSelectors; i++)
{
if (selector == ((long*)(*gSelectors))[i])
{
SetA4 (oldA4);
return i;
}
}
SetA4 (oldA4);
return -1;
}
// The selector function
pascal
OSErr
MySelectorFunction
(
OSType selector,
long* response
)
{
long oldA4 = SetCurrentA4 ();
long patchIndex = -1;
OSErr err = noErr;
patchIndex = FindPatch(selector);
if (patchIndex < 0)
{
err = Gestalt(selector, response);
}
else
{
*response = ((long*)(*gValues))[patchIndex];
}
SetA4 (oldA4);
return err;
}
// Public entry to find a selector
pascal OSErr FindSelector(OSType selector, long* value)
{
long oldA4 = SetCurrentA4 ();
OSErr err = noErr;
long response = 0;
long patchIndex = -1;
patchIndex = FindPatch(selector);
if (patchIndex >= 0)
{
response = ((long*)(*gValues))[patchIndex];
*value = response;
}
else
{
err = Gestalt(selector, value);
}
SetA4 (oldA4);
return err;
}
// Make an entry in the tables
OSErr SetGestaltRoutine(OSType selector)
{
long oldA4 = SetCurrentA4 ();
OSErr err = noErr;
SelectorFunctionUPP oldFcn;
err = ReplaceGestalt(selector, MySelectorFunction, &oldFcn);
if (err == gestaltUndefSelectorErr)
{
err = NewGestalt(selector, MySelectorFunction);
if (err == noErr)
{
err = ReplaceGestalt(selector, MySelectorFunction, &oldFcn);
}
}
SetA4 (oldA4);
return err;
}
// Register a selector
pascal OSErr RegisterSelector(OSType selector, long value)
{
long oldA4 = SetCurrentA4 ();
OSErr err = noErr;
long patchIndex = -1;
patchIndex = FindPatch(selector);
if (patchIndex < 0)
{
if ((gAllocSize % kAllocChunk) == 0)
{
gAllocSize += kAllocChunk;
if (gSelectors)
{
SetHandleSize(gSelectors, gAllocSize);
}
else
{
gSelectors = NewHandle(gAllocSize * sizeof(long));
}
if (gValues)
{
SetHandleSize(gValues, gAllocSize * sizeof(long));
}
else
{
gValues = NewHandle(gAllocSize);
}
patchIndex = gPatchCount;
gPatchCount++;
}
}
(((long*)(*gSelectors))[patchIndex]) = selector;
(((long*)(*gValues))[patchIndex]) = value;
SetGestaltRoutine(selector);
SetA4 (oldA4);
return (err);
}